#ifndef OBJECT_H
#define OBJECT_H

#include <vector>

#include "src/math/trio.h"
#include "src/math/vector3d.h"
#include "src/math/transformation.h"

#include "src/scene/material.h"
#include "src/scene/ray.h"
#include "src/scene/hbb/box.h"

class NearestInfo;

class Object{
    public:
        Object(int = 0, int _type = 0, bool = true);
        Object(const Material &, int = 0, int _type = 0, bool = true);
        Object(const Material &, const Vector3D &, int = 0, int _type = 0, bool = true);
        Object(const Material &, const Vector3D &, int, int, bool, const Matrix &, const Matrix &);
        Object(const Material &, const Vector3D &, int, int, bool, const Transformation &);
        virtual ~Object();

        int getId() const;
        void setId(int);

        const Material &getMaterial() const;
        void setMaterial(const Material &);
        void addTexture(Texture *_t) {material.texture = _t;};
        void addBumpMapping(BumpMapping *_bm) {material.bumpMapping = _bm;};

        const Vector3D &getCenter() const;
        void setCenter(const Vector3D &);

        const HBBBox &getBoundingBox() const {return boundingBox;};
        HBBBox *getBoundingBoxPointer() {return &boundingBox;};
//
//        void setRelativePosition(const Vector3D &);
//        const Vector3D &getRelativePosition() const {return relativePosition;};

        const Transformation &getTransformation() const {return transformation;};

        bool isSelected() const;
        void select(bool);

        bool isPrimitive() const;
        int getType() const;

        bool needCaustic() const;

        Object *getParent() const {return parent;};
        void setParent(Object *_p) {parent = _p;};

        void translate(const Vector3D &);
        void rotate(double, const Vector3D &, const Vector3D & = Vector3D(0,0,0), bool = false);
        void scale(const Vector3D &, const Vector3D & = Vector3D(0,0,0), bool = false);

        virtual double volume() const{return 0;};
        virtual double area() const{return 0;};

        virtual void draw(bool, bool = false, const Material & = Material()) const = 0;
        bool hit(const Ray &, NearestInfo *);
        virtual std::vector<Trio> intersection(const Ray &) const = 0;
        virtual Vector3D normal(const Vector3D &) const;
        Material chooseMaterial(bool, bool, const Material &) const;

        virtual void getTextureUV(double *, double *, const Vector3D &, unsigned int) const = 0;
        virtual void getLocalMinMax(Vector3D *, Vector3D *) const = 0;

    protected:
        virtual void setBoundingBox() = 0;
        void boundingBoxWithTransformation(const Vector3D &, const Vector3D &);

        bool drawBegin(bool, bool, const Material &, double *, double *, double *, double *) const;
        void drawEnd(bool, bool) const;

        int id;
        int type;
        bool primitive;
        bool selected;
        Material material;
        Vector3D center;//ponto menos centro
//        Vector3D relativePosition;
        Transformation transformation;
        HBBBox boundingBox;
        Object *parent;
};

#endif
